/*
 * File Name：AsyncHttpRequest.java
 * Copyright：Copyright 2008 - 2012 CiWong.Inc. All Rights Reserved.
 * Description： AsyncHttpRequest.java
 * Modify By：jejun
 * Modify Date：2012-10-28
 * Modify Type：Add
 */
package com.ciwong.libs.utils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * 异步网络访问公共类,增加了在用Post访问时调用都可以设置Post参数跟Get参数
 * 
 * @author jejun
 * @version ciwong v.1.0 2012-10-28
 * @since ciwong v.1.0
 */
public class AsyncHttpRequest extends AsyncTask<Object, Integer, Object>
{
    private static final String TAG = "AsyncHttpRequest";

    public static final boolean DEBUG = false;

    /**
     * HTTP网络连接超时时间
     */
    private static final int HTTP_CONNECT_TIME_OUT = 6000;

    /**
     * HTTP请求响应超时时间
     */
    private static final int HTTP_RESPONSE_TIME_OUT = 10000;

    /**
     * get请求方式
     */
    public static final int REQUEST_GET = 1;

    /**
     * post请求方式
     */
    public static final int REQUEST_POST = 2;

    /**
     * put请求方式
     */
    public static final int REQUEST_PUT = 3;

    /**
     * delete请求方式
     */
    public static final int REQUEST_DELETE = 4;

    /**
     * 上传附件
     */
    public static final int REQUEST_POST_ATTACHMENT = 5;

    /**
     * 结果类型：字符串
     */
    public static final int RESULT_DATA_TYPE_STRING = 1;

    /**
     * 结果类型：指定对象
     */
    public static final int RESULT_DATA_TYPE_OBJECT = 3;

    /**
     * 结果类型：sax handler(调用者传入的解析xml的Handler)
     */
    public static final int RESULT_DATA_TYPE_XML_HANDLER = 4;

    /**
     * 结果类型：上传图片返回的数据(返回类实体用List<ImageUpload>)
     */
    public static final int RESULT_DATA_TYPE_ATTACHMENT_UPLOAD = 5;

    /**
     * 结果类型：下载图片
     */
    public static final int RESULT_DATA_TYPE_BITMAP = 6;

    /**
     * 请求无错误
     */
    public static final int REQUEST_ERROR_NONE = 0;

    /**
     * 请求错误：输入的请求地址有误
     */
    public static final int REQUEST_ERROR_URL = 1;

    /**
     * 请求错误：执行请求发生异常
     */
    public static final int REQUEST_ERROR_EXCEPTION = 2;

    /**
     * 请求错误：服务器内部出错
     */
    public static final int REQUEST_ERROR_500 = 500;

    /**
     * 请求错误：请求的地址找不到
     */
    public static final int REQUEST_ERROR_404 = 404;

    /**
     * 请求错误：网络未连接
     */
    public static final int REQUEST_ERROR_NET_UNCONNECT = 3;

    /**
     * 请求错误：请求超时
     */
    public static final int REQUEST_ERROR_TIME_OUT = 4;

    /**
     * 请求错误：传入的文件有误
     */
    public static final int REQUEST_ERROR_FILE = 5;

    /**
     * 请求错误：验证信息有误
     */
    public static final int REQUEST_ERROR_VERIFY = 6;

    /**
     * 请求错误：token过期或无效果
     */
    public static final int REQUEST_ERROR_ACCESSTOKEN = 7;

    /**
     * 请求错误：证书无效或没有
     */
    public static final int REQUEST_ERROR_SSL = 8;

    /**
     * 请求错误：上传附件出错
     */
    public static final int REQUEST_ERROR_UPLOAD_1 = 9;

    /**
     * 请求错误：上传附件已成功但转换结果时出错
     */
    public static final int REQUEST_ERROR_UPLOAD_2 = 10;

    /**
     * 数据错误，请求成功，返回的数据不对
     */
    public static final int REQUEST_ERROR_DATA = 11;

    /**
     * 请求动作
     */
    public static final String REQUEST_ACTION = "action";

    /**
     * 请求动作-动态
     */
    public static final String REQUEST_ACTION_DYNAMIC = "action_dynamic";

    /**
     * 模块名称
     */
    public static final String REQUEST_MODULES = "REQUEST_MODULES";

    public static final String ECODING = "utf-8";

    private String url;

    private HttpMethod request;

    private GetMethod getMethod;

    private PostMethod postMethod;

    private PutMethod putMethod;

    private DeleteMethod deleteMethod;

    private int requestType = REQUEST_GET;

    private Map<String, String> getParams;

    private Map<String, String> postParams;

    private Object objectParams;

    private int resultDataType = RESULT_DATA_TYPE_STRING;

    private Class<?> resultClazz;

    private Type resultType;// 反射类型

    protected int errorType = REQUEST_ERROR_NONE;

    protected Activity mActivity;

    private RequestCallback mRequestCallback;

    private int httpRequestTimeOut, httpResponseTimeOut;

    private CWXmlHandler mXmlHandler;

    private List<InputStream> attachmentStreams;// 附件输入流

    private String[] attachmentNames;// 附件表单名称

    private String loadMsg;// 加载信息

    private boolean isShowLoadDialog = true;// 是否显示加载对话框

    private boolean isConcatPostParams;// 是否需要拼接Post参数方式

    private boolean isRestJsonApi;// 是否模拟rest json Api的方式

    private boolean isShowToast = true;// 是需要显示Toast

    private static List<String> noVerifyActions;// 不需要验证身份的动作

    private boolean verifyAction = true;// 是否需要验证身份信息

    private static VerifyInfo mVerifyInfo;// 验证信息

    private static String tmpuid;// 验证临时userId信息

    private static Map<String, CWAction> mActions;// 新增Action

    private static RequestCallback mErrorCallback;// 请求失败回调

    private int requestCount;// 当一次请求失败时,允许再次请求的次数

    private int requestMaxCount = 3;// 允许再次请求的最大次数

    private boolean isUserUrl;// 是否是是用户自定义的地址

    private Object requestTag;// 请求标识,用于代码复用

    private static CWGetVerifyInfo getVerifyInfoInterface;

    private Map<String, String> headers;

    /**
     * 附加返回字段名
     */
    private String append;

    private boolean canceled;

    public String clsName;

    private void registerProtocol()
    {
        @SuppressWarnings("deprecation")
        Protocol https = new Protocol("https",
                new CWSecureProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", https);
    }

    private void unregisterProtocol()
    {
        Protocol.unregisterProtocol("https");
    }

    /**
     * 构造函数
     * 
     * @param mActivity
     *            上下文
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(Activity mActivity, RequestCallback mRequestCallback)
    {
        this.mActivity = mActivity;
        this.mRequestCallback = mRequestCallback;
    }

    /**
     * 构造函数(注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(RequestCallback mRequestCallback)
    {
        isShowLoadDialog = false;
        isShowToast = false;
        this.mRequestCallback = mRequestCallback;
    }

    /**
     * 设置请求连接超时时间
     * 
     * @param timeOut
     *            超时时间
     */
    public void setTimeOut(int timeOut)
    {
        httpRequestTimeOut = timeOut;
    }

    /**
     * 设置请求响应超时时间
     * 
     * @param timeOut
     *            超时时间
     */
    public void setResponseTimeOut(int timeOut)
    {
        httpResponseTimeOut = timeOut;
    }

    /**
     * 构造函数
     * 
     * @param mActivity
     * @param url
     * @param mRequestCallback
     */
    public AsyncHttpRequest(Activity mActivity, String url,
            RequestCallback mRequestCallback)
    {
        this.mActivity = mActivity;
        this.url = url;
        this.mRequestCallback = mRequestCallback;
        isUserUrl = true;
    }

    /**
     * 构造函数(注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param url
     *            自定义的地址
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(String url, RequestCallback mRequestCallback)
    {
        this.url = url;
        this.mRequestCallback = mRequestCallback;
        isUserUrl = true;
        isShowLoadDialog = false;
        isShowToast = false;
    }

    /**
     * 构造函数(注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param url
     *            自定义的地址
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(String url, Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this.url = url;
        this.mRequestCallback = mRequestCallback;
        isUserUrl = true;
        this.getParams = params;
        isShowLoadDialog = false;
        isShowToast = false;
    }

    /**
     * 
     * 构造函数
     * 
     * @param mActivity
     *            上下文
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(Activity mActivity, Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this.mActivity = mActivity;
        this.getParams = params;
        this.mRequestCallback = mRequestCallback;
    }

    /**
     * 
     * 构造函数(注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this.getParams = params;
        this.mRequestCallback = mRequestCallback;
        isShowLoadDialog = false;
        isShowToast = false;
    }

    /**
     * 
     * 构造函数(需要上传附件时用)
     * 
     * @param mActivity
     *            上下文
     * @param attach
     *            附件
     * @param attachmentName
     *            发送请求时附件的参数名称(默认为attachment)
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(Activity mActivity, File attach,
            String attachmentName, Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this(mActivity, params, mRequestCallback);
        verifyAction = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
        try
        {
            this.attachmentStreams = new ArrayList<InputStream>();
            this.attachmentStreams.add(new FileInputStream(attach));
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        this.attachmentNames = new String[1];
        this.attachmentNames[0] = attachmentName;
    }

    /**
     * 
     * 构造函数(需要上传附件时用)<br />
     * (注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param mActivity
     *            上下文
     * @param attach
     *            附件
     * @param attachmentName
     *            发送请求时附件的参数名称(默认为attachment)
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(File attach, String attachmentName,
            Map<String, String> params, RequestCallback mRequestCallback)
    {
        this(params, mRequestCallback);
        verifyAction = false;
        isShowLoadDialog = false;
        isShowToast = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
        try
        {
            this.attachmentStreams = new ArrayList<InputStream>();
            this.attachmentStreams.add(new FileInputStream(attach));
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        this.attachmentNames = new String[1];
        this.attachmentNames[0] = attachmentName;
    }

    /**
     * 构造函数(需要上传附件时用),批量上传附件
     * 
     * @param attach
     * @param attachNames
     * @param params
     * @param mRequestCallback
     */
    public AsyncHttpRequest(Activity mContext, File[] attach,
            String[] attachNames, Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this(mContext, params, mRequestCallback);
        verifyAction = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
        try
        {
            this.attachmentStreams = new ArrayList<InputStream>();
            for (File file : attach)
            {
                this.attachmentStreams.add(new FileInputStream(file));
            }
            this.attachmentNames = attachNames;
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 构造函数(需要上传附件时用),批量上传附件<br />
     * (注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param attach
     * @param attachNames
     * @param params
     * @param mRequestCallback
     */
    public AsyncHttpRequest(File[] attach, String[] attachNames,
            Map<String, String> params, RequestCallback mRequestCallback)
    {
        this(params, mRequestCallback);
        verifyAction = false;
        isShowLoadDialog = false;
        isShowToast = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
        try
        {
            this.attachmentStreams = new ArrayList<InputStream>();
            for (File file : attach)
            {
                this.attachmentStreams.add(new FileInputStream(file));
            }
            this.attachmentNames = attachNames;
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 
     * 构造函数(需要上传附件时用)
     * 
     * @param mActivity
     *            上下文
     * @param attachStream
     *            附件输入流
     * @param attachmentName
     *            发送请求时附件的参数名称(默认为attachment)
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(Activity mActivity, InputStream attachStream,
            String attachmentName, Map<String, String> params,
            RequestCallback mRequestCallback)
    {
        this(mActivity, params, mRequestCallback);
        verifyAction = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.attachmentStreams = new ArrayList<InputStream>();
        this.attachmentStreams.add(attachStream);
        this.attachmentNames = new String[1];
        this.attachmentNames[0] = attachmentName;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
    }

    /**
     * 
     * 构造函数(需要上传附件时用)<br />
     * (注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param attachStream
     *            附件输入流
     * @param attachmentName
     *            发送请求时附件的参数名称(默认为attachment)
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     */
    public AsyncHttpRequest(InputStream attachStream, String attachmentName,
            Map<String, String> params, RequestCallback mRequestCallback)
    {
        this(params, mRequestCallback);
        verifyAction = false;
        isShowLoadDialog = false;
        isShowToast = false;
        this.requestType = REQUEST_POST_ATTACHMENT;
        this.attachmentStreams = new ArrayList<InputStream>();
        this.attachmentStreams.add(attachStream);
        this.attachmentNames = new String[1];
        this.attachmentNames[0] = attachmentName;
        this.resultDataType = RESULT_DATA_TYPE_ATTACHMENT_UPLOAD;
        init();
    }

    /**
     * 构造函数
     * 
     * @param mActivity
     *            上下文
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     * @param requestType
     *            请求方式(REQUEST_GET或REQUEST_POST)
     */
    public AsyncHttpRequest(Activity mActivity, Map<String, String> params,
            RequestCallback mRequestCallback, int requestType)
    {
        this(mActivity, params, mRequestCallback);
        this.requestType = requestType;
        init();
    }

    /**
     * 构造函数<br />
     * (注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     * @param requestType
     *            请求方式(REQUEST_GET或REQUEST_POST)
     */
    public AsyncHttpRequest(Map<String, String> params,
            RequestCallback mRequestCallback, int requestType)
    {
        this(params, mRequestCallback);
        isShowLoadDialog = false;
        isShowToast = false;
        this.requestType = requestType;
        init();
    }

    /**
     * 构造函数<br />
     * (注:该构造方法创建的实例不会提示加载进度条跟土司提示信息)
     * 
     * @param o
     *            请求json参数结构体
     * @param params
     *            请求参数
     * @param mRequestCallback
     *            执行请求完成(无论是否成功)后调用的方法
     * @param requestType
     *            请求方式(REQUEST_GET或REQUEST_POST)
     */
    public AsyncHttpRequest(Object o, Map<String, String> params,
            RequestCallback mRequestCallback, int requestType)
    {
        this(params, mRequestCallback);
        isShowLoadDialog = false;
        isShowToast = false;
        this.requestType = requestType;
        this.objectParams = o;
        init();
    }

    private void init()
    {
        if (this.requestType == REQUEST_POST
                || this.requestType == REQUEST_POST_ATTACHMENT
                || this.requestType == REQUEST_PUT)
        {
            if (postParams == null)
            {
                this.postParams = new HashMap<String, String>();
            }
            this.postParams.putAll(this.getParams);
            // this.getParams = null;
            isConcatPostParams = true;
        }
    }

    /**
     * 设置请求失败时重复请求的最大次数
     * 
     * @param maxCount
     *            最大次数
     */
    public void setRequestMaxCount(int maxCount)
    {
        this.requestMaxCount = maxCount;
    }

    /**
     * 设置请求方式
     * 
     */
    public void setRequestType(int requestType)
    {
        this.requestType = requestType;
        if (REQUEST_POST == requestType && getParams != null)
        {
            postParams = getParams;
        }
    }

    /**
     * 设置自己的请求URL
     * 
     * @param url
     */
    public void setUrl(String url)
    {
        this.url = url;
    }

    /**
     * 设置验证信息
     * 
     * @param mInfo
     *            {@link VerifyInfo}
     */
    public static void setVerifyInfo(VerifyInfo mInfo)
    {
        AsyncHttpRequest.mVerifyInfo = mInfo;
    }

    public static void setVerifyInfo(VerifyInfo mInfo, String tmpuid)
    {
        AsyncHttpRequest.mVerifyInfo = mInfo;
        AsyncHttpRequest.tmpuid = tmpuid;
    }

    /**
     * 获取验证信息
     * 
     * @return
     */
    public static VerifyInfo getVerifyInfo()
    {
        if (AsyncHttpRequest.mVerifyInfo != null)
        {
            return AsyncHttpRequest.mVerifyInfo;
        }
        else if (getVerifyInfoInterface != null)
        {
            mVerifyInfo = getVerifyInfoInterface.getVerfyInfo();
            return mVerifyInfo;
        }
        return null;
    }

    /**
     * 设置错误回调
     * 
     * @param errorCallback
     *            {@link RequestCallback}
     */
    public static void setErrorCallback(RequestCallback errorCallback)
    {
        AsyncHttpRequest.mErrorCallback = errorCallback;
    }

    public static String getAppendStr(VerifyInfo mVerifyInfo)
    {
        if (mVerifyInfo != null)
        {
            // return "client_id=" + mVerifyInfo.getClientId() +
            // "&access_token="
            // + mVerifyInfo.getAccessToken() + "&openid="
            // + mVerifyInfo.getOpenId() + "&oauth_version="
            // + mVerifyInfo.getOauthVersion() + "&scope="
            // + mVerifyInfo.getScope() + "&clientip="
            // + mVerifyInfo.getClientIp() + "&token_uid=" + tmpuid;
            return "client_id=" + mVerifyInfo.getClientId() + "&access_token="
                    + mVerifyInfo.getAccessToken() + "&openid="
                    + mVerifyInfo.getOpenId() + "&oauth_version="
                    + mVerifyInfo.getOauthVersion() + "&scope="
                    + mVerifyInfo.getScope() + "&clientip="
                    + mVerifyInfo.getClientIp() + "&termtype="
                    + mVerifyInfo.getTermType();

        }
        return "";
    }

    public static void setGetVerifyInfoInterface(
            CWGetVerifyInfo getVerifyInfoInterface)
    {
        AsyncHttpRequest.getVerifyInfoInterface = getVerifyInfoInterface;
    }

    /**
     * 判断身份验证信息是否为空
     * 
     * @return 身份验证信息是否为空
     */
    public static boolean isVerifyInfoNull()
    {
        return mVerifyInfo == null;
    }

    /**
     * 禁用请求默认的进度对话框
     * 
     */
    public void disableProgressDialog()
    {
        this.isShowLoadDialog = false;
    }

    /**
     * 禁用访问出错时显示Toast,方便自已定义
     */
    public void disableToast()
    {
        isShowToast = false;
    }

    /**
     * 禁用身份验证
     * 
     */
    public void disableVerifyAction()
    {
        this.verifyAction = false;
    }

    /**
     * 设置请求头
     * 
     * @param headers
     *            请求头
     */
    public void setHeaders(Map<String, String> headers)
    {
        this.headers = headers;
    }

    /**
     * 
     * 设置网络请求返回附加字段(返回类型为long类型)
     * 
     * @param append
     *            附加字段名
     */
    public void setAppend(String append)
    {
        this.append = append;
    }

    /**
     * 添加不需要身份验证的动作
     * 
     * @param action
     *            请求动作
     */
    public static void addNoVerifyAction(String action)
    {
        if (noVerifyActions == null)
        {
            noVerifyActions = new ArrayList<String>();
        }
        noVerifyActions.add(action);
    }

    /**
     * 自定义加载时显示的信息
     * 
     * @param msg
     *            显示的信息
     */
    public void setLoadMsg(String msg)
    {
        this.loadMsg = msg;
    }

    /**
     * 在执行请求完后，若需要将数据转换成一个类对象，则必须要设置对象的Class .
     * 
     * @param clazz
     *            对象class
     */
    public void setResultClazz(Class<?> clazz)
    {
        this.resultClazz = clazz;
    }

    /**
     * 
     * 在执行请求完后，若需要将数据转换成一个类对象，则必须要设置对象的Type<br />
     * 方法: Type t = new TypeToken<自己类的名称>(){}.getType();
     * 
     * @param type
     *            type
     */
    public void setResultType(Type type)
    {
        this.resultType = type;
    }

    /**
     * 设置解析xml的sax Handler类<br />
     * 
     * @param mHandler
     *            xml Handler
     */
    public void setXmlHandler(CWXmlHandler mHandler)
    {
        this.mXmlHandler = mHandler;
    }

    /**
     * 设置调用者所需的数据的类型<br />
     * 
     * @param type
     *            数据类型<br />
     *            {@link AsyncHttpRequest.RESULT_DATA_TYPE_STRING}
     *            {@link AsyncHttpRequest.RESULT_DATA_TYPE_STREAM}
     *            {@link AsyncHttpRequest.RESULT_DATA_TYPE_OBJECT}
     */
    public void setResultType(int type)
    {
        this.resultDataType = type;
    }

    public void cancelTask()
    {
        this.canceled = true;
    }

    /**
     * 添加请求Action
     * 
     * @param mAction
     *            {@link CWAction}
     * 
     * @param clsName
     *            action的完整类名，作为hashmap里面的key
     */
    public static void addRequestAction(String clsName, CWAction mAction)
    {
        if (mActions == null)
        {
            mActions = new HashMap<String, CWAction>();
        }
        if (!mActions.containsKey(clsName))
        {
            mActions.put(clsName, mAction);
        }
    }

    /**
     * 设置GET请求参数
     * 
     * @param params
     *            请求参数
     */
    public void setParams(Map<String, String> params)
    {
        this.getParams = params;
    }

    /**
     * 获取GET请求参数
     * 
     * @return 请求参数
     */
    public Map<String, String> getParams()
    {
        return this.getParams;
    }

    /**
     * 设置POST请求参数
     * 
     * @param params
     *            请求参数
     */
    public void setPostParams(Map<String, String> params)
    {
        this.postParams = params;
    }

    /**
     * 获取POST请求参数
     * 
     * @return 请求参数
     */
    public Map<String, String> getPostParams()
    {
        return this.postParams;
    }

    @Override
    protected void onPreExecute()
    {
        // if (isShowLoadDialog)
        // {
        // if (this.loadMsg == null)
        // {
        // this.loadMsg = CWResource.getString("loading", mActivity);
        // }
        // cwProgressBar = new CWProgressBar(mActivity);
        // cwProgressBar.setMessage(this.loadMsg);
        // cwProgressBar.setCancelable(true);
        // cwProgressBar.setCanceledOnTouchOutside(false);
        // if (mActivity != null && !mActivity.isFinishing())
        // {
        // cwProgressBar.show();
        // }
        // }
    }

    /**
     * 执行请求
     * 
     * @return 返回值
     * @throws IOException
     */
    private Object excuteReq()
    {
        requestCount++;
        Object retVal = null;
        errorType = REQUEST_ERROR_NONE;
        if (request != null)
        {
            request.releaseConnection();
        }
        try
        {
            if (this.requestType != REQUEST_POST_ATTACHMENT)
            {
                retVal = request();
            }
            else
            {
                retVal = postAttachment();
            }
        }
        catch (Exception e)
        {
            if (e instanceof java.net.ConnectException
                    || e instanceof java.net.SocketTimeoutException)
            {
                this.errorType = REQUEST_ERROR_TIME_OUT;
            }
            else if (e instanceof javax.net.ssl.SSLHandshakeException)
            {
                this.errorType = REQUEST_ERROR_SSL;
            }
            else if (e instanceof IllegalStateException)
            {
                this.errorType = REQUEST_ERROR_URL;
            }
            else
            {
                this.errorType = REQUEST_ERROR_EXCEPTION;
            }
            e.printStackTrace();
            CWLog.i("debug", "requestCount:" + requestCount
                    + "       requestMaxCount:" + requestMaxCount
                    + "    errorType:" + this.errorType);
            if (errorType == REQUEST_ERROR_TIME_OUT
                    || errorType == REQUEST_ERROR_EXCEPTION)
            {
                if (requestCount < requestMaxCount)
                {
                    retVal = excuteReq();
                }
            }
            // dismissProgress();
        }
        return retVal;
    }

    /**
     * 启用验证信息
     * 
     */
    public void enableVerifyAction()
    {
        verifyAction = true;
    }

    /**
     * 
     * {@inheritDoc}
     */
    @Override
    protected Object doInBackground(Object... paras)
    {
        if (paras != null && paras.length > 0)
        {
            requestTag = paras[0];
        }
        if (mActions == null && this.url == null)
        {
            throw new NullPointerException(
                    "请调用setRequestAction(CWAction) 方法设置你所需要的请求动作");
        }
        Object retVal = null;
        String action = null;
        String action_dynamic = null;
        String modules = null;
        Map<String, String> params = (this.requestType == REQUEST_GET || this.requestType == REQUEST_DELETE) ? getParams
                : postParams;
        if (params != null)
        {
            modules = params.get(REQUEST_MODULES);
            action = params.get(REQUEST_ACTION);
            action_dynamic = params.get(REQUEST_ACTION_DYNAMIC);
            params.remove(REQUEST_MODULES);
            params.remove(REQUEST_ACTION);
            params.remove(REQUEST_ACTION_DYNAMIC);
        }
        if (!isUserUrl)
        {
            CWAction cwAction = mActions.get(modules);
            if (cwAction != null)
            {
                this.url = cwAction
                        .getActionUrl(action_dynamic == null ? action
                                : action_dynamic);
            }
            else
            {
                for (CWAction ac : mActions.values())
                {
                    String tmpAc = ac
                            .getActionUrl(action_dynamic == null ? action
                                    : action_dynamic);
                    if (tmpAc != null)
                    {
                        this.url = tmpAc;
                    }
                }
            }
            if (action_dynamic != null)
            {
                Iterator<String> it = params.keySet().iterator();
                ArrayList<String> dynamicParams = new ArrayList<String>();
                while (it.hasNext())
                {
                    String key;
                    String value;
                    key = it.next().toString();
                    value = params.get(key);
                    if (key.startsWith("{") && key.endsWith("}"))
                    {
                        if (key != null && value != null)
                        {
                            this.url = this.url.replace(key, value);
                        }
                        else
                        {
                            CWLog.e("request", "key=" + key + "&value=" + value);
                        }
                        dynamicParams.add(key);
                    }
                }
                for (int i = 0; i < dynamicParams.size(); i++)
                {
                    params.remove(dynamicParams.get(i));
                }
            }
        }
        if (this.url != null)
        {
            if (verifyAction)
            {
                if (getVerifyInfo() != null)
                {
                    if (this.url.lastIndexOf("?") != this.url.length() - 1)
                    {
                        this.url += "?";
                    }
                    this.url += getAppendStr(mVerifyInfo);
                }
                else
                {
                    CWLog.e("request", "请设置验证信息!");
                    this.errorType = REQUEST_ERROR_VERIFY;
                }
            }
            else if (getParams != null && !getParams.isEmpty())
            {
                if (this.url.lastIndexOf("?") != this.url.length() - 1)
                {
                    this.url += "?";
                }
            }
            if (tmpuid != null)
            {
                if (this.url.contains("?"))
                {
                    this.url += "&token_uid=" + tmpuid;
                }
                else
                {
                    this.url += "?token_uid=" + tmpuid;
                }
            }
            if (NetworkUtils.isOnline())
            {
                final boolean isHttps = this.url.startsWith("https");
                if (isHttps)
                {
                    registerProtocol();
                }
                retVal = excuteReq();
                if (isHttps)
                {
                    unregisterProtocol();
                }
            }
            else
            {
                this.errorType = REQUEST_ERROR_NET_UNCONNECT;
            }
        }
        else
        {
            this.errorType = REQUEST_ERROR_URL;
        }
        if (request != null)
        {
            request.releaseConnection();
        }
        return retVal;
    }

    /**
     * 一般的get或post请求
     * 
     * @return Object
     * @throws IOException
     */
    private Object request() throws Exception
    {
        Object retVal = null;
        if (requestType == REQUEST_GET)
        {
            getMethod = HttpHelper.getGetConnection(getParams, url, headers);
            CWLog.i(TAG, "requestType=" + requestType + "-->URL:"
                    + getMethod.getURI().toString());
        }
        else if (requestType == REQUEST_POST)
        {
            if (isConcatPostParams)
            {
                url = HttpHelper.concatUrl(postParams, url);
            }
            postMethod = HttpHelper.getPostConnection(objectParams, postParams,
                    url, headers, isRestJsonApi);
            CWLog.i(TAG, "requestType=" + requestType + "-->URL:"
                    + postMethod.getURI().toString());
        }
        else if (requestType == REQUEST_PUT)
        {
            url = HttpHelper.concatUrl(postParams, url);
            putMethod = HttpHelper.getPutConnection(objectParams, url, headers,
                    isRestJsonApi);
            CWLog.i(TAG, "requestType=" + requestType + "-->URL:"
                    + putMethod.getURI().toString());
        }
        else if (requestType == REQUEST_DELETE)
        {
            deleteMethod = HttpHelper.getDeleteConnection(getParams, url,
                    headers);
            CWLog.i(TAG, "requestType=" + requestType + "-->URL:"
                    + deleteMethod.getURI().toString());
        }
        if (getMethod != null || postMethod != null || putMethod != null
                || deleteMethod != null)
        {
            retVal = excuteRequest();
        }
        return retVal;
    }

    /**
     * 执行请求
     * 
     * @return object Object
     * @throws IOException
     *             IOException
     */
    private Object excuteRequest() throws IOException
    {
        Object retVal = null;
        HttpClient client = new HttpClient();
        client.getHttpConnectionManager()
                .getParams()
                .setConnectionTimeout(
                        httpRequestTimeOut > 0 ? httpRequestTimeOut
                                : HTTP_CONNECT_TIME_OUT);
        client.getHttpConnectionManager()
                .getParams()
                .setSoTimeout(
                        httpResponseTimeOut > 0 ? httpResponseTimeOut
                                : HTTP_RESPONSE_TIME_OUT);
        if (this.requestType == AsyncHttpRequest.REQUEST_GET)
        {
            client.executeMethod(getMethod);
            request = getMethod;
        }
        else if (this.requestType == AsyncHttpRequest.REQUEST_POST)
        {
            client.executeMethod(postMethod);
            request = postMethod;
        }
        else if (this.requestType == AsyncHttpRequest.REQUEST_PUT)
        {
            client.executeMethod(putMethod);
            request = putMethod;
        }
        else if (this.requestType == AsyncHttpRequest.REQUEST_DELETE)
        {
            client.executeMethod(deleteMethod);
            request = deleteMethod;
        }

        StatusLine resultCode = request.getStatusLine();
        CWLog.i("debug", "StatusLine:" + resultCode);
        CWLog.i("debug", "url:" + request.getURI().toString());
        switch (resultCode.getStatusCode())
        {
            case HttpStatus.SC_OK:
                errorType = REQUEST_ERROR_NONE;
                switch (this.resultDataType)
                {
                    case RESULT_DATA_TYPE_XML_HANDLER:
                        if (mXmlHandler != null)
                        {
                            InputStream stream = null;
                            try
                            {
                                stream = request.getResponseBodyAsStream();
                                SAXParserFactory saxparserfactory = SAXParserFactory
                                        .newInstance();
                                SAXParser saxparser = saxparserfactory
                                        .newSAXParser();
                                saxparser.parse(stream, mXmlHandler);
                                retVal = mXmlHandler;
                            }
                            catch (Exception e)
                            {
                                e.printStackTrace();
                            }
                            finally
                            {
                                if (stream != null)
                                {
                                    stream.close();
                                }
                            }
                        }
                        break;
                    case RESULT_DATA_TYPE_BITMAP:
                        InputStream in = request.getResponseBodyAsStream();
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        byte[] buff = new byte[1024];
                        int len;
                        while ((len = in.read(buff)) > 0)
                        {
                            out.write(buff, 0, len);
                        }
                        out.flush();
                        out.close();
                        in.close();
                        buff = out.toByteArray();
                        retVal = BitmapFactory.decodeByteArray(buff, 0,
                                buff.length);
                        break;
                    default:
                        final String result = input2String(
                                request.getResponseBodyAsStream(),
                                request.getResponseHeader("Content-Encoding"));
                        switch (this.resultDataType)
                        {
                            case RESULT_DATA_TYPE_ATTACHMENT_UPLOAD:
                                try
                                {
                                    Gson mGson = new Gson();
                                    Type t = new TypeToken<List<AttachmentUpload>>()
                                    {
                                    }.getType();
                                    String json = (String) result;
                                    CWLog.i("debug", "上传附件结果:" + result);
                                    json = json.replace("\"", "\\\"")
                                            .replace("'", "\"")
                                            .replace("result:", "\"result\":")
                                            .replace("msg:", "\"msg\":");
                                    json = json.replace("}{", "},{");
                                    List<AttachmentUpload> uploads = mGson
                                            .fromJson("[" + json + "]", t);
                                    retVal = uploads;
                                }
                                catch (Exception e)
                                {
                                    this.errorType = REQUEST_ERROR_UPLOAD_2;
                                    e.printStackTrace();
                                }
                                break;

                            case RESULT_DATA_TYPE_OBJECT:
                                try
                                {
                                    Gson mGson = new Gson();
                                    final String json = (String) result;
                                    JSONObject jsonObject = new JSONObject(json);
                                    Object object = null;
                                    if (jsonObject.has("data"))
                                    {
                                        String dataJson = jsonObject
                                                .getString("data");
                                        if (dataJson != null
                                                && !"".equals(dataJson))
                                        {
                                            if (resultClazz != null)
                                            {
                                                object = mGson.fromJson(
                                                        dataJson, resultClazz);
                                            }
                                            else if (resultType != null)
                                            {
                                                object = mGson.fromJson(
                                                        dataJson, resultType);
                                            }
                                        }
                                    }
                                    final int retCode = jsonObject
                                            .getInt("ret");
                                    final String msg = jsonObject
                                            .getString("msg");
                                    long appendValue = 0;
                                    if (jsonObject.has(append))
                                    {
                                        appendValue = jsonObject
                                                .getLong(append);
                                    }
                                    if (jsonObject.has("errcode"))
                                    {
                                        final int errcode = jsonObject
                                                .getInt("errcode");
                                        retVal = new Object[]{object, retCode,
                                                errcode, msg, appendValue};
                                    }
                                    else
                                    {
                                        retVal = new Object[]{object, retCode,
                                                msg, appendValue};
                                    }
                                }
                                catch (JSONException e)
                                {
                                    e.printStackTrace();
                                }
                                break;
                            default:
                                retVal = result;
                                break;
                        }
                        break;
                }
                break;
            default:
                this.errorType = resultCode.getStatusCode();
                CWLog.i("debug", "StatusLine:" + resultCode
                        + "&mErrorCallback=" + mErrorCallback);
                if (mErrorCallback != null)
                {
                    mErrorCallback.error(errorType);
                }
                break;
        }
        return retVal;
    }

    /**
     * 上传附件
     * 
     * @return 返回信息
     * @throws IOException
     */
    private Object postAttachment() throws IOException
    {
        String connUrl = this.url;
        if (connUrl != null)
        {
            connUrl = HttpHelper.concatUrl(this.getParams, connUrl);
            postMethod = new PostMethod(connUrl);
            int index = this.attachmentStreams.size();
            int paramSize = this.postParams == null
                    || this.postParams.isEmpty() ? 0 : this.postParams.size();
            Part[] parts = new Part[index + paramSize];
            if (this.attachmentStreams != null)
            {
                for (int i = 0; i < index; i++)
                {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    int len;
                    byte[] buffer = new byte[1024];
                    try
                    {
                        final InputStream attachmentStream = attachmentStreams
                                .get(i);
                        while ((len = attachmentStream.read(buffer)) > 0)
                        {
                            out.write(buffer, 0, len);
                        }
                        out.flush();
                        out.close();
                        String name = "file";
                        ByteArrayPartSource source = new ByteArrayPartSource(
                                name, out.toByteArray());
                        parts[i] = new FilePart(name, source, null, ECODING);
                    }
                    catch (IOException e)
                    {
                        this.errorType = REQUEST_ERROR_FILE;
                        e.printStackTrace();
                    }
                }
            }
            else
            {
                this.errorType = REQUEST_ERROR_FILE;
            }
            if (paramSize > 0)
            {
                for (String key : this.postParams.keySet())
                {
                    parts[index] = new StringPart(key, postParams.get(key),
                            ECODING);
                    index++;
                }
            }
            postMethod.setRequestEntity(new MultipartRequestEntity(parts,
                    postMethod.getParams()));
            // HttpHelper.initRequest(postMethod);
            // postMethod.addRequestHeader("Content-Type",
            // "multipart/form-data");
        }
        Object retVal = null;
        if (this.errorType == REQUEST_ERROR_NONE)
        {
            retVal = excuteRequest();
        }
        return retVal;
    }

    /**
     * 
     * 将输入流转换成字符串
     * 
     * @param is
     *            输入流
     * @param header
     *            网络响应头Content-Encoding字段
     * @return 字符串
     */
    private String input2String(InputStream is, Header header)
    {
        if (header != null && header.getValue() != null
                && header.getValue().equalsIgnoreCase("gzip"))
        {
            return gzip2String(is);
        }
        else
        {
            return none2String(is);
        }
    }

    /**
     * 将输入流转换成字符串
     * 
     * @param stream
     *            输入流
     * @return 字符串
     */
    private String none2String(InputStream stream)
    {
        // BufferedReader reader;
        StringBuilder sb = new StringBuilder();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            // reader = new BufferedReader(new InputStreamReader(stream,
            // ECODING));
            // String buffer;
            // byte[] b = new byte[4096];
            // for (int n; (n = stream.read(b)) != -1;)
            // {
            // sb.append(new String(b, 0, n,"utf-8"));
            // }
            // while ((buffer = reader.readLine()) != null)
            // {
            // sb.append(buffer);
            // }
            int i = -1;
            while ((i = stream.read()) != -1)
            {
                baos.write(i);
            }
            return baos.toString();
        }
        catch (UnsupportedEncodingException e1)
        {
            e1.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                baos.close();
                stream.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * 
     * 将压缩后的输入流换成字符串
     * 
     * @param is
     *            压缩后的输入流
     * @return 字符串
     */
    @SuppressWarnings("finally")
    private String gzip2String(InputStream is)
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            GZIPInputStream gis = new GZIPInputStream(is);

            int count;
            byte data[] = new byte[1024];
            while ((count = gis.read(data, 0, data.length)) != -1)
            {
                baos.write(data, 0, count);
            }
            gis.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            return baos.toString();
        }
    }

    /**
     * 获取错误的文字提示资源id
     * 
     * @param errType
     *            错误类型
     * @return 资源id
     */
    public static String getErrorTipRsId(int errType, Context act)
    {
        String resId = null;
        try
        {
            switch (errType)
            {

                case REQUEST_ERROR_URL:
                case REQUEST_ERROR_404:
                case REQUEST_ERROR_500:
                case REQUEST_ERROR_EXCEPTION:
                    resId = "对不起,请求数据失败";
                    break;
                case REQUEST_ERROR_VERIFY:
                    resId = "验证信息错误";
                    break;
                case REQUEST_ERROR_NET_UNCONNECT:
                    resId = "网络不可用,请设置网络";
                    break;
                case REQUEST_ERROR_TIME_OUT:
                    resId = "网络不给力,请稍后尝试";
                    break;
                case REQUEST_ERROR_FILE:
                    resId = "传入的文件有误";
                    break;
                case REQUEST_ERROR_SSL:
                    resId = "证书有误";
                    break;
                case REQUEST_ERROR_DATA:
                    resId = "数据错误";
                    break;
                case REQUEST_ERROR_NONE:
                    resId = null;
                    break;
            }
        }
        catch (Exception e)
        {
            resId = null;
        }
        return resId;
    }

    /**
     * 启用是否模拟拼接post参数的方式
     * 
     */
    public void enableConcatPostParams()
    {
        isConcatPostParams = true;
    }

    /**
     * 禁用是否模拟拼接post参数的方式
     * 
     */
    public void disableConcatPostParams()
    {
        isConcatPostParams = false;
    }

    /**
     * 启用是否模拟rest json Api的方式
     * 
     */
    public void enableRestJsonApi()
    {
        isRestJsonApi = true;
    }

    /**
     * 
     * 禁用是否模拟rest json Api的方式
     * 
     */
    public void disableRestJsonApi()
    {
        isRestJsonApi = false;
    }

    /**
     * 
     * {@inheritDoc}
     */
    @Override
    protected void onPostExecute(Object result)
    {
        if (canceled)
        {
            return;
        }
        boolean success = false;
        String resId = getErrorTipRsId(this.errorType, mActivity);
        success = (resId == null && this.errorType == REQUEST_ERROR_NONE) ? true
                : false;
        if (mRequestCallback != null)
        {
            if (success)
            {
                switch (resultDataType)
                {
                    case RESULT_DATA_TYPE_OBJECT:
                        if (result != null)
                        {
                            Object[] objects = (Object[]) result;
                            if (requestTag == null)
                            {
                                if (objects.length == 4)
                                {
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (String) objects[2]);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Long) objects[3],
                                            (String) objects[2]);
                                }
                                else
                                {
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (String) objects[3]);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Integer) objects[2],
                                            (String) objects[3]);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Long) objects[4],
                                            (String) objects[3]);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Integer) objects[2],
                                            (Long) objects[4],
                                            (String) objects[3]);
                                }
                            }
                            else
                            {
                                if (objects.length == 4)
                                {
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (String) objects[2], requestTag);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Long) objects[3],
                                            (String) objects[2], requestTag);
                                }
                                else
                                {
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (String) objects[3], requestTag);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Integer) objects[2],
                                            (String) objects[3], requestTag);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Long) objects[4],
                                            (String) objects[3], requestTag);
                                    mRequestCallback.success(objects[0],
                                            (Integer) objects[1],
                                            (Integer) objects[2],
                                            (Long) objects[4],
                                            (String) objects[3], requestTag);
                                }
                            }
                        }
                        else
                        {
                            this.errorType = REQUEST_ERROR_DATA;
                            onPostExecute(null);
                        }
                        break;
                    case RESULT_DATA_TYPE_XML_HANDLER:
                        CWXmlHandler xmlHandler = (CWXmlHandler) result;
                        if (xmlHandler != null)
                        {
                            if (requestTag == null)
                            {
                                mRequestCallback.success(xmlHandler,
                                        xmlHandler.getRet(),
                                        xmlHandler.getMsg());
                            }
                            else
                            {
                                mRequestCallback.success(xmlHandler,
                                        xmlHandler.getRet(),
                                        xmlHandler.getMsg(), requestTag);
                            }
                        }
                        else
                        {
                            CWLog.e("debug", "解释XML出错");
                        }
                        break;
                    case RESULT_DATA_TYPE_STRING:
                        if (requestTag == null)
                        {
                            mRequestCallback.success((String) result);
                        }
                        else
                        {
                            mRequestCallback.success((String) result,
                                    requestTag);
                        }
                        break;
                    case RESULT_DATA_TYPE_ATTACHMENT_UPLOAD:
                        if (mRequestCallback != null)
                        {
                            if (requestTag == null)
                            {
                                mRequestCallback.success(result, 0, "");
                            }
                            else
                            {
                                mRequestCallback.success(result, 0, "",
                                        requestTag);
                            }
                        }
                        break;
                    case RESULT_DATA_TYPE_BITMAP:
                        if (mRequestCallback != null)
                        {
                            if (requestTag == null)
                            {
                                mRequestCallback.success((Bitmap) result);
                            }
                            else
                            {
                                mRequestCallback.success((Bitmap) result,
                                        requestTag);
                            }
                        }
                }
            }
            else
            {
                if (resId != null && isShowToast)
                {
                    // CWToast.error(mActivity, resId).show();
                }
                if (requestTag == null)
                {
                    mRequestCallback.error(errorType);
                }
                else
                {
                    mRequestCallback.error(errorType, requestTag);
                }
            }
            // dismissProgress();
        }
    }

    @Override
    protected void onCancelled()
    {
        CWLog.i("debug", "onCancelled1");
        if (request != null)
        {
            request.recycle();
            request.releaseConnection();
            CWLog.i("debug", "onCancelled2");
        }
        // dismissProgress();
    }

    // public void dismissProgress()
    // {
    // if (cwProgressBar != null && !this.mActivity.isFinishing()
    // && cwProgressBar.isShowing())
    // {
    // cwProgressBar.dismiss();
    // }
    // }

    /**
     * 请求执行完成后调用的方法类
     * 
     * @author jejun
     * 
     */
    public abstract static class RequestCallback
    {
        /**
         * 请求成功，并传递字符串数据
         * 
         * @param result
         *            字符串数据
         */
        public void success(String result)
        {
        }

        /**
         * 请求成功，并传递字符串数据
         * 
         * @param result
         *            字符串数据
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(String result, Object requestTag)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param msg
         *            返回状态信息
         */
        public void success(Object data, int resultCode, String msg)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param appendValue
         *            附加字段返回值
         * @param msg
         *            返回状态信息
         */
        public void success(Object data, int resultCode, long appendValue,
                String msg)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param errcode
         *            错误码
         * @param appendValue
         *            附加字段返回值
         * @param msg
         *            返回状态信息
         */
        public void success(Object data, int resultCode, int errcode,
                long appendValue, String msg)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param errcode
         *            错误码
         * @param msg
         *            返回状态信息
         */
        public void success(Object data, int resultCode, int errcode, String msg)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param msg
         *            返回状态信息
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(Object data, int resultCode, String msg,
                Object requestTag)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param resultCode
         *            返回状态码
         * @param appendValue
         *            附加字段返回值
         * @param msg
         *            返回状态信息
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(Object data, int resultCode, long appendValue,
                String msg, Object requestTag)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param errcode
         *            错误码
         * @param resultCode
         *            返回状态码
         * @param msg
         *            返回状态信息
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(Object data, int resultCode, int errcode,
                String msg, Object requestTag)
        {
        }

        /**
         * 成功时调用方法<br />
         * 传入一个指定的对象<br />
         * 如果指定返回类型为上传附件返回的类型(RESULT_DATA_TYPE_ATTACHMENT_UPLOAD)Ojbect类型固定为List
         * <{@link AttachmentUpload}>
         * 
         * @param result
         *            对象(如果json字符串中不包含data字段数据，则返回null)
         * @param errcode
         *            错误码
         * @param resultCode
         *            返回状态码
         * @param appengValue
         *            附加字段返回值
         * @param msg
         *            返回状态信息
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(Object data, int resultCode, int errcode,
                long appendValue, String msg, Object requestTag)
        {
        }

        /**
         * 
         * 成功时调用方法<br />
         * 传入调用者指定的xml sax Handler
         * 
         * @param xmlHandler
         */
        public void success(CWXmlHandler xmlHandler, int ret, String msg)
        {
        }

        /**
         * 
         * 成功时调用方法<br />
         * 传入调用者指定的xml sax Handler
         * 
         * @param xmlHandler
         * @param ret
         * @param msg
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(CWXmlHandler xmlHandler, int ret, String msg,
                Object requestTag)
        {
        }

        /**
         * 上传附件成功时调用方法<br />
         * 
         * @param resultCode
         *            返回码
         * @param msg
         *            返回信息
         */
        public void success(int resultCode, String msg)
        {
        }

        /**
         * 上传附件成功时调用方法<br />
         * 
         * @param resultCode
         *            返回码
         * @param msg
         *            返回信息
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(int resultCode, String msg, Object requestTag)
        {
        }

        /**
         * 成功时调用方法<br />
         * 图片
         * 
         * @param mBitmap
         */
        public void success(Bitmap mBitmap)
        {
        }

        /**
         * 成功时调用方法<br />
         * 图片
         * 
         * @param mBitmap
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void success(Bitmap mBitmap, Object requestTag)
        {
        }

        /**
         * 请求出错时调用方法
         * 
         * @param errorType
         *            错误类型
         */
        public void error(int errorType)
        {

        }

        /**
         * 请求出错时调用方法
         * 
         * @param errorType
         *            错误类型
         * @param requestTag
         *            请求标识(多用于代码复用)
         */
        public void error(int errorType, Object requestTag)
        {

        }

    }

    /**
     * 上传文件返回实体类
     * 
     * @author PLA-ZJLIU
     * 
     */
    public static class AttachmentUpload
    {
        private int result;

        private String msg;

        private Info info;

        public int getResult()
        {
            return result;
        }

        public void setResult(int result)
        {
            this.result = result;
        }

        public String getMsg()
        {
            return msg;
        }

        public void setMsg(String msg)
        {
            this.msg = msg;
        }

        public Info getInfo()
        {
            return info;
        }

        public void setInfo(Info info)
        {
            this.info = info;
        }

        /**
         * 文件信息
         * 
         * @author PLA-ZJLIU
         * 
         */
        public static class Info
        {
            private String image;

            private String file;

            private Size size;

            public String getImage()
            {
                return image;
            }

            public void setImage(String image)
            {
                this.image = image;
            }

            public String getFile()
            {
                return file;
            }

            public void setFile(String file)
            {
                this.file = file;
            }

            public Size getSize()
            {
                return size;
            }

            public void setSize(Size size)
            {
                this.size = size;
            }
        }

        /**
         * 大小
         * 
         * @author PLA-ZJLIU
         * 
         */
        public static class Size
        {
            private int width;

            private int height;

            public int getWidth()
            {
                return width;
            }

            public void setWidth(int width)
            {
                this.width = width;
            }

            public int getHeight()
            {
                return height;
            }

            public void setHeight(int height)
            {
                this.height = height;
            }
        }
    }

    /**
     * 验证信息
     * 
     * @author PLA-ZJLIU
     * 
     */
    public static class VerifyInfo implements Serializable
    {
        /**
         *  
         */
        private static final long serialVersionUID = 1870726433982307905L;

        private String clientId;//

        private String accessToken;

        private String openId;

        private String oauthVersion;

        private String scope;//

        private String clientIp;// ip地址

        private String expiresIn;

        private String refreshToken;

        private String tokenType;

        private int termType;

        public String getClientId()
        {
            return clientId;
        }

        public void setClientId(String clientId)
        {
            this.clientId = clientId;
        }

        public String getAccessToken()
        {
            return accessToken;
        }

        public void setAccessToken(String accessToken)
        {
            this.accessToken = accessToken;
        }

        public String getOpenId()
        {
            return openId;
        }

        public void setOpenId(String openId)
        {
            this.openId = openId;
        }

        public String getOauthVersion()
        {
            return oauthVersion;
        }

        public void setOauthVersion(String oauthVersion)
        {
            this.oauthVersion = oauthVersion;
        }

        public String getScope()
        {
            return scope;
        }

        public void setScope(String scope)
        {
            this.scope = scope;
        }

        public String getClientIp()
        {
            return clientIp;
        }

        public void setClientIp(String clientIp)
        {
            this.clientIp = clientIp;
        }

        public String getExpiresIn()
        {
            return expiresIn;
        }

        public void setExpiresIn(String expiresIn)
        {
            this.expiresIn = expiresIn;
        }

        public String getRefreshToken()
        {
            return refreshToken;
        }

        public void setRefreshToken(String refreshToken)
        {
            this.refreshToken = refreshToken;
        }

        public String getTokenType()
        {
            return tokenType;
        }

        public void setTokenType(String tokenType)
        {
            this.tokenType = tokenType;
        }

        public int getTermType()
        {
            return termType;
        }

        public void setTermType(int termType)
        {
            this.termType = termType;
        }

    }

    /**
     * 
     * 习网父Xml解释类
     * 
     * @author PLA-ZJLIU
     * 
     */
    public static class CWXmlHandler extends DefaultHandler
    {
        private int ret;// 返回说明

        private int errcode;// 二级错误字段【参数错误】说明

        private String msg;// 解释信息

        private String qName;

        /**
         * 返回说明
         * 
         * @return 返回说明
         */
        public int getRet()
        {
            return ret;
        }

        /**
         * 
         * 二级错误字段【参数错误】说明
         * 
         * @return 二级错误字段【参数错误】说明
         */
        public int getErrcode()
        {
            return errcode;
        }

        /**
         * 解释信息
         * 
         * @return 解释信息
         */
        public String getMsg()
        {
            return msg;
        }

        /**
         * <b style="color:red">重写时必须调用父类方法(super.startElement)</b><br />
         * {@inheritDoc}
         */
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException
        {
            this.qName = qName;
        }

        /**
         * <b style="color:red">重写时必须调用父类方法(super.characters)</b><br />
         * {@inheritDoc}
         */
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException
        {
            String value = new String(ch, start, length);
            if ("ret".equals(qName))
            {
                ret = Integer.parseInt(value);
            }
            else if ("errcode".equals(qName))
            {
                errcode = Integer.parseInt(value);
            }
            else if ("msg".equals(qName))
            {
                msg = value;
            }
        }

        /**
         * <b style="color:red">重写时必须调用父类方法(super.endElement)</b><br />
         * {@inheritDoc}
         */
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException
        {
            this.qName = null;
        }
    }

    /**
     * 习网网络请求地址接口
     * 
     * @author PLA-ZJLIU
     */
    public static interface CWAction
    {

        /**
         * 获取请求地址
         * 
         * @param action
         *            action
         * @return url 网络请求地址
         */
        public String getActionUrl(String action);

    }

    /**
     * 获取token接口
     * 
     * @author RES-KUNZHU
     * 
     */
    public interface CWGetVerifyInfo
    {
        VerifyInfo getVerfyInfo();
    }

    /**
     * 文件服务器action
     * 
     * @author RES-KUNZHU
     * 
     */
    public static interface UploadFileAction extends CWAction
    {
        public void changeUploadServer();
    }

    /**
     * 
     * @author PLA-ZJLIU
     * 
     */
    public static class CWSecureProtocolSocketFactory implements
            SecureProtocolSocketFactory
    {

        private SSLContext sslcontext = null;

        private SSLContext createSSLContext()
        {
            SSLContext sslcontext = null;
            try
            {
                sslcontext = SSLContext.getInstance("SSL");
                sslcontext.init(null,
                        new TrustManager[]{new TrustAnyTrustManager()},
                        new java.security.SecureRandom());
            }
            catch (NoSuchAlgorithmException e)
            {
                try
                {
                    sslcontext = SSLContext.getInstance("TLS");
                    sslcontext.init(null,
                            new TrustManager[]{new TrustAnyTrustManager()},
                            new java.security.SecureRandom());

                }
                catch (Exception e2)
                {
                    e.printStackTrace();
                }
            }
            catch (KeyManagementException e)
            {
                e.printStackTrace();
            }
            return sslcontext;
        }

        private SSLContext getSSLContext()
        {
            if (this.sslcontext == null)
            {
                this.sslcontext = createSSLContext();
            }
            return this.sslcontext;
        }

        public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException, UnknownHostException
        {
            return getSSLContext().getSocketFactory().createSocket(socket,
                    host, port, autoClose);
        }

        public Socket createSocket(String host, int port) throws IOException,
                UnknownHostException
        {
            return getSSLContext().getSocketFactory().createSocket(host, port);
        }

        public Socket createSocket(String host, int port,
                InetAddress clientHost, int clientPort) throws IOException,
                UnknownHostException
        {
            return getSSLContext().getSocketFactory().createSocket(host, port,
                    clientHost, clientPort);
        }

        public Socket createSocket(String host, int port,
                InetAddress localAddress, int localPort,
                HttpConnectionParams params) throws IOException,
                UnknownHostException, ConnectTimeoutException
        {
            if (params == null)
            {
                throw new IllegalArgumentException("Parameters may not be null");
            }
            int timeout = params.getConnectionTimeout();
            SocketFactory socketfactory = getSSLContext().getSocketFactory();
            if (timeout == 0)
            {
                return socketfactory.createSocket(host, port, localAddress,
                        localPort);
            }
            else
            {
                Socket socket = socketfactory.createSocket();
                SocketAddress localaddr = new InetSocketAddress(localAddress,
                        localPort);
                SocketAddress remoteaddr = new InetSocketAddress(host, port);
                socket.bind(localaddr);
                socket.connect(remoteaddr, timeout);
                return socket;
            }
        }

        // 自定义私有类
        private static class TrustAnyTrustManager implements X509TrustManager
        {

            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException
            {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException
            {
            }

            public X509Certificate[] getAcceptedIssuers()
            {
                return new X509Certificate[]{};
            }
        }

    }

}
